package com.heima.comment.service.impl;


import com.alibaba.fastjson.JSON;
import com.heima.aliyun.GreenTextScan;
import com.heima.comment.service.CommentHotService;
import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustException;
import com.heima.feigns.UserFeign;
import com.heima.model.comment.dtos.CommentDTO;
import com.heima.model.comment.dtos.CommentLikeDTO;
import com.heima.model.comment.dtos.CommentSaveDTO;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.constants.HotArticleConstants;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.mess.app.NewBehaviorDTO;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    CommentHotService commentHotService;
    @Autowired
    RabbitTemplate rabbitTemplate;


    /**
     * 发表评论功能
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDTO dto) {
        /**
         * 1. 校验参数
         *    校验是否登录
         *    校验文章id   校验内容不为空  校验内容长度不能大于140个字符 (validated校验)
         * 2. 阿里云校验评论内容是否违规
         *   简单:  此步不做      普通: 阿里云检测有问题提示      高级:  有问题不报异常，替换为**)
         * 3. 远程查询当前登陆用户信息
         * 4. 创建评论信息，并保存到mongo
         */
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            CustException.cust(AppHttpCodeEnum.NEED_LOGIN);
        }
        String content = dto.getContent();
        String filteredContent = "";
        try {
            //TODO 过滤功能未开启 有BUG
            Map map = greenTextScan.greenTextScan2(content);
            System.out.println("map = " + map);
            filteredContent = (String) map.get("filteredContent");

        } catch (Exception exception) {
            exception.printStackTrace();
        }
        ResponseResult<ApUser> result = userFeign.findUserById(user.getId());
        if(result.getCode()!=0 || result.getData() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE, "当前登录信息有误");
        }
        user = result.getData();
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setImage(user.getImage());
        apComment.setContent(filteredContent);
        apComment.setArticleId(dto.getArticleId());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setType((short) 0);
        apComment.setFlag((short) 0);
        mongoTemplate.save(apComment);

        NewBehaviorDTO mess = new NewBehaviorDTO();
        mess.setType(NewBehaviorDTO.BehaviorType.COMMENT);
        mess.setArticleId(dto.getArticleId());
        mess.setAdd(1);
        rabbitTemplate.convertAndSend(HotArticleConstants.HOT_ARTICLE_SCORE_BEHAVIOR_QUEUE, JSON.toJSONString(mess));

        return ResponseResult.okResult(apComment);
    }

    /**
     * 点赞评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDTO dto) {
        /**
         * 1. 参数校验
         *    评论id不能为空  operation必须为 0  或  1
         * 2. 根据评论id查询评论数据， 为null返回错误信息
         * 3. 如果是点赞操作 判断是否已经点赞
         *    点过赞提示 请勿重复点赞
         *    未点过赞   保存点赞信息到mongo
         *    并修改评论信息的点赞数量( + 1)
         * 4. 如果是取消点赞操作
         *    删除点赞信息
         *    并修改评论信息的点赞数量( - 1) , 要判断下别减成负数
         * 5. 返回结果时，需要返回点赞点赞数量  返回的key要求必须是:  likes
         */
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //根据评论id查询评论数据
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //根据作者id，评论id查询评论数据
        ApCommentLike apCommentLike = mongoTemplate.findOne(
                Query.query(Criteria.where("authorId").is(user.getId())
                        .and("commentId").is(dto.getCommentId())
                ),
                ApCommentLike.class);
        Short operation = dto.getOperation();
        //判断是否为点赞状态
        if (apCommentLike != null && operation.intValue() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST, "已点赞");
        }
        if (operation.intValue() == 0) { //点赞
            // 点赞+1
            apComment.setLikes(apComment.getLikes() + 1);
            mongoTemplate.save(apComment);

            // 保存评论点赞信息
            apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(user.getId());
            apCommentLike.setCommentId(apComment.getId());
            apCommentLike.setOperation(dto.getOperation());
            mongoTemplate.save(apCommentLike);

            //计算热点评论评论
            if (apComment.getLikes() >= 10 && apComment.getFlag().shortValue() == 0) {
                commentHotService.hotCommentExecutor(apComment);
            }
        } else {
            // 取消点赞
            apComment.setLikes(
                    apComment.getLikes() <= 0 ? 0: apComment.getLikes() - 1);
            mongoTemplate.save(apComment);

            //删除点赞评论信息
            mongoTemplate.remove( Query.query( Criteria.
                    where("authorId").is(user.getId())
                    .and("commentId").is(apComment.getId()) ), ApCommentLike.class);
        }
        //数据回显
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("likes",apComment.getLikes());
        return ResponseResult.okResult(resultMap);
    }

    /**
     * 查询评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDTO dto) {
        //1 参数检查
        if (dto == null || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer size = dto.getSize();
        if ( size == null || size <= 0) {
            size = 10;
        }
        // 判断是否
        //2 查询Mongo文章所有评论列表
        List<ApComment> apCommentList;
        // 文章评论的首页
        if(dto.getIndex().intValue() == 1){
            //查询热点评论  5
            Query query = Query.query(Criteria.where("articleId").is(dto.getArticleId()).and("flag").is(1)).with(Sort.by(Sort.Direction.DESC, "likes"));
            apCommentList = mongoTemplate.find(query, ApComment.class);
            // 热点集合不为空
            if (CollectionUtils.isNotEmpty(apCommentList)) {
                size = size - apCommentList.size();
                List<ApComment> normalComments = mongoTemplate.find(getQuery(dto, size), ApComment.class);
                apCommentList.addAll(normalComments);
            }else {
                apCommentList = mongoTemplate.find(
                        getQuery(dto,size),
                        ApComment.class
                );
            }
        }else {
            apCommentList = mongoTemplate.find(
                    getQuery(dto,size),
                    ApComment.class
            );
        }

        //3 封装查询结果
        //3.1 用户未登录 直接返回评论列表
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.okResult(apCommentList);
        }
        //3.2 用户登录，需要加载当前用户对评论点赞的列表
        // 获取文章对应的所有评论ID列表
        List<String> idList = apCommentList.stream()
                .map(ApComment::getId)
                .collect(Collectors.toList());

        // 查询 点赞批量列表 按照评论id 筛选
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(
                Query.query(Criteria.where("commentId").in(idList)
                        .and("authorId").is(user.getId()))
                , ApCommentLike.class);

        // 遍历当前用户点赞列表 和当前评论列表
        if(CollectionUtils.isNotEmpty(apCommentList)
                && CollectionUtils.isNotEmpty(apCommentLikes)){
            // 获取点过赞的评论id
            List<String> commentIds = apCommentLikes.stream()
                    .map(ApCommentLike::getCommentId).collect(Collectors.toList());
            // 遍历评论列表，将comment 转为 commentVO
            return ResponseResult.okResult( apCommentList.stream()
                    .map(comment -> parseCommentVO(comment,commentIds)));
        }
        return ResponseResult.okResult(apCommentList);
    }
    /**
     * 将comment 转为 vo对象   根据likes情况判断是否点过赞
     * @param apComment
     * @param commentIds
     * @return
     */
    private ApCommentVo parseCommentVO(ApComment apComment,List<String> commentIds){
        ApCommentVo apCommentVo = new ApCommentVo();
        BeanUtils.copyProperties(apComment, apCommentVo);
        //遍历当前用户点赞列表
        if (commentIds.contains(apCommentVo.getId())){
            apCommentVo.setOperation((short) 0);
        }
        return apCommentVo;
    }
    /**
     * 构建查询条件
     */
    private Query getQuery(CommentDTO dto, Integer size) {
        return Query.query(Criteria.where("articleId").is(dto.getArticleId())
                .and("flag").is(0).and("createdTime").lt(dto.getMinDate()))
                .limit(size).with(Sort.by(Sort.Direction.DESC, "createdTime"));
    }

}
